#include "plist.h"
#include "pnf_mng.h"

namespace {
	string temp, keyer;
	void next_line(std::ifstream& ifile, string& line) {
		line.clear();
		do {
			getline(ifile, temp); trim(temp, line);
		} while (line.empty());
	}
	string str0;
	string getValue(const string& key, const string& line) {
		keyer = "<" + key + ">";
		auto pos = line.find(keyer);
		if (pos == string::npos) {
			return str0;
		}
		temp = line.substr(pos + keyer.length());
		keyer = "</" + key + ">";
		pos = temp.find(keyer);
		if (pos == string::npos) {
			return str0;
		}
		return temp.substr(0, pos);
	}

	string trim(const string& line) {
		return getValue("key", line);
	}

	vector<string> strs;
	void toValue(const string& line, int& v1, int& v2) {
		split(getValue("string", line), ",", strs);
		strs[0].erase(strs[0].begin());
		strs[1].pop_back();
		v1 = std::atoi(strs[0].c_str());
		v2 = std::atoi(strs[1].c_str());
	}

	void toValue(const string& line, int& v1, int& v2, int& v3, int& v4) {
		keyer = getValue("string", line);
		temp.clear();
		for (const auto& c : keyer) {
			if (c == '{' || c == '}') {
				continue;
			}
			temp.push_back(c);
		}
		split(temp, ",", strs);
		v1 = std::atoi(strs[0].c_str());
		v2 = std::atoi(strs[1].c_str());
		v3 = std::atoi(strs[2].c_str());
		v4 = std::atoi(strs[3].c_str());
	}
}


bool read_plist(std::ifstream& ifile, string& line, Node& node) {
	node.name = trim(line);
	// <dict>
	next_line(ifile, line);
	node.index = 0; 
	node.ox = node.oy = node.sx = node.sy = 0;
	string key;
	while (true) {
		next_line(ifile, line);
		if (line == "</dict>") {
			break;
		}
		key = trim(line);
		next_line(ifile, line);
		if (key == "aliases") {

		} else if (key == "spriteOffset" || key == "offset") {
			toValue(line, node.sx, node.sy);
		} else if (key == "spriteSize") {
			toValue(line, node.sw, node.sh);
		} else if (key == "spriteSourceSize" || key == "sourceSize") {
			toValue(line, node.ow, node.oh);
		} else if (key == "textureRect" || key == "frame") {
			toValue(line, node.x, node.y, node.w, node.h);
		} else if (key == "textureRotated" || key == "rotated") {
			node.rotate = (line.find("true") != string::npos) || (line.find("TRUE") != string::npos);
		} else if (key == "sourceColorRect") {
			toValue(line, node.ox, node.oy, node.sw, node.sh);
		}
	}


	if (node.sx != 0) {
	}
	if (node.sx != 0) {
	}

	return true;
}


bool read_plist(std::ifstream& ifile, string& line, Plist& plist) {
	string key;
	while (true) {
		next_line(ifile, line);
		if (line == "</dict>") {
			break;
		}
		key = trim(line);
		next_line(ifile, line);
		if (key == "format") {
			plist.format = std::atoi(getValue("integer", line).c_str());
		} else if (key == "pixelFormat") {
			plist.pixelFormat = line;
		} else if (key == "premultiplyAlpha") {
			plist.premultiplyAlpha = (line.find("true") != string::npos) || (line.find("TRUE") != string::npos);
		} else if (key == "realTextureFileName") {
			plist.realTextureFileName = line;
		} else if (key == "size") {
			toValue(line, plist.width, plist.height);
		} else if (key == "smartupdate") {
			
		} else if (key == "textureFileName") {
			plist.textureFileName = line;
		}
	}
	return true;
}


bool anti_plist(const string& path, const string& filename, bool print_nodes) {
	std::ifstream ifile(path + filename);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_INTENSITY | FOREGROUND_RED);

	if (!ifile.is_open()) {
		cout << "plist open fail" << endl;
		return false;
	}
	Plist plist;
	Node node;
	string line, temp;
	while (true) {
		next_line(ifile, line);
		if (line.find("<?xmlversion=") != string::npos ||
			line.find("!DOCTYPEplist") != string::npos ||
			line.find("plist version=") != string::npos) {
			continue;
		}
		if (line == "<key>frames</key>") {
			// <dict>
			next_line(ifile, line);
			// <key>xxx.png</key>
			next_line(ifile, line);
			break;
		}
	}

	do {
		read_plist(ifile, line, node);
		plist.nodes.push_back(node);
		// </dict> or <key>xxx.png</key>
		next_line(ifile, line);
		if (line == "</dict>") {
			break;
		}
	} while (true);

	while (!ifile.eof()) {
		// <key>metadata</key>
		next_line(ifile, line);
		// <dict>
		next_line(ifile, line);
		read_plist(ifile, line, plist);
		break;
	}
	ifile.close();

	if (plist.nodes.empty()) {
		cout << " plist empty" << endl;
		return false;
	}

	if (plist.pixelFormat.find("RGBA8888") == string::npos) {
		// cout << "pixelFormat is not RGBA8888" << endl;
		// return false;
	}

	if (plist.realTextureFileName != plist.textureFileName) {
		cout << "textureFileName is not realTextureFileName" << endl;
		return false;
	}

	if (plist.textureFileName.find("pvr.ccz") == string::npos) {
		cout << "textureFileName is not .pvr.ccz" << endl;
		return false;
	}

	for (const auto& node : plist.nodes) {
		// if (node.index != 1) {
		// 	cout << "aliases is not empty" << endl;
		// 	return false;
		// }
		if (node.sw != node.w || node.sh != node.h) {
			cout << "spriteSize is not textureSize" << endl;
			return false;
		}
	}

	auto file_name = filename.substr(0, filename.length() - 6);

	int width = 0, height = 0;
	auto ptr = read_png(path + file_name + ".png", width, height);
	if (ptr == nullptr) {
		cout << "png read fail" << endl;
		return false;
	}

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);

	auto make_dir = path + file_name + "\\";
	CreateDirectory(make_dir.c_str(), NULL);
	for (const auto& node : plist.nodes) {
		auto arr = clip_png(ptr, width, node);
		save_png(make_dir + node.name, arr, node.ow, node.oh);
		// delete[] arr;
		if (print_nodes) {
			cout << node.name.substr(0, node.name.length() - 4) << ".";
		}
	}
	delete[] ptr;
	cout << endl;
	return true;
}
